package gas.model;

import java.util.*;

/**
 *
 * Class that manages the data structure to manage admins and users.
 *
 * @author cs120fao
 *
 */

 /***************************************
  * UserBase
  * pre: exists ability to enter users into data structure for analysis
  * post: appropriately updated userbase after executing requests
  */
public class UserBase {
    private ArrayList<User> userTable = new ArrayList<User>();
    private HashMap<Integer, User> userMap = new HashMap<Integer, User>();
    
    /***************************************
     * Constructor (default)
     * pre: none
     * post: default UserBase is created, initialized to null
     * return: none
     */
    public UserBase(){}
    
    /***************************************
     * createUserAccount
     * pre: s - String
     *      pw - String
     *      email - String
     * post: desiredUser has correctly formatted members
     * return: null - if username, password, or email are incorrectly formatted
     *         desiredUser - new User with correctly formatted members
     */
    public User createUserAccount( String s, String pw, String email){
      User desiredUser = new User();
      if ( !desiredUser.setUsername(s) ){
        System.err.println("Username not correctly formatted.");
        return null;
      }
      //IA: username is now correctly formatted
      //    length>=6, not already in database
      
      if ( !desiredUser.changePassword(pw) ){
        System.err.println("Password not correctly formatted.");
        return null;
      }
      //IA: password is now correctly formatted
      //    length>=6, at least one capital letter, at least one lowercase letter, at least one number
      
      if ( !desiredUser.setEmail(email) ){
        System.err.println("Email not correctly formatted.");
        return null;
      }
      //IA: email is now correctly formatted
      
//    desiredUser.setID(id);
      
      //IA: all of desiredUser's members are correctly formatted
      userTable.add(desiredUser);
      //IA: desiredUser is now in userTable
      return desiredUser;
    }
    /***************************************
     * createUserAccount
     * pre: s - String
     *      pw - String
     *      email - String
     *      ID - positive Integer
     * post: retUser has correctly formatted members
     *       retUser is paired with a unique ID number
     *       the ID and retUser are put into userMap
     * return: retUser - new User with correctly formatted members
     */
    /*** WRAPPER ***/
    public User createUserAccount( String s, String pw, String email, Integer ID){
        User retUser = createUserAccount(s,pw,email);
        //IA: retUser has correctly formatted members
        if (retUser != null){
            //IA: retUser exists
            int insertID = ID.intValue();
            //insertID is positive
            while(this.userMap.containsKey(new Integer(insertID))) insertID++;    
            //IA: insertID now has a positive value that does not exist in userMap
            this.userMap.put(new Integer(insertID), retUser);
            //IA: userMap now contains a positive ID and the new user
        }
        return retUser;
    }
    
    /***************************************
     * getUserTable
     * pre: none
     * post: none
     * return: userTable
     */
    public ArrayList<User> getUserTable(){ return this.userTable; }
    
    /***************************************
     * getUserMap
     * pre: none
     * post: none
     * return: userMap
     */
    public HashMap<Integer, User> getUserMap(){ return this.userMap; }
    
    //TODO: Possibly need to change from index to searchable.
/*
    public void upgradeUser(int index){
      Admin newAdmin = Admin.upgradeUser(this.userTable.get(index));
      
      this.userTable.remove(index);
      this.userTable.add(newAdmin);
    }
*/    
    /***************************************
     * upgradeUser
     * pre: id - Integer (index of user)
     * post: user with id is upgraded to admin with same id
     * return: none
     */
    public void upgradeUser(Integer id){
//      System.err.print("Upgrading user:");
        Admin newAdmin = null;
 
        User upgradeUser = this.userMap.get(id); //id.getValue() like in createUserAccount?
        
        if (upgradeUser != null){
//          System.err.println("ok!");
            newAdmin = Admin.upgradeUser(upgradeUser);
        }
        //IA: newAdmin is valid copy of user
//      else System.err.println("could not find....");
        
        this.userMap.remove(id);
        if (newAdmin != null) this.userMap.put(id, newAdmin);
    }

    /***************************************
     * getUser
     * pre: userName - String
     *      user data structure exists
     * post: none
     * return: retUser - user with username passed in by parameter
     */
    public User getUser(String userName){
        User retUser = null;
        for (User u : userMap.values())
            if(retUser != null) break;
            else if (userName.equals(u.getUsername())) retUser = u;
        return retUser;
    }

    public static boolean selfTest(){
      System.out.println("Running UserBase Tests");
      boolean passAll = true;
      UserBase testUserBase = new UserBase();
      
      //Testing Good Creation of user.
      passAll = passAll & testUserBase.createUserAccount("testUser", "testPassword1", "test@email.com") != null;
      //Testing Bad Creation of user.
      passAll = passAll & (testUserBase.createUserAccount("testUser", "testPassword", "test@email.com") == null );
      passAll = passAll & ( testUserBase.getUserTable().size() == 1 ) ;

      //Testing Upgrade to Admin
/*    testUserBase.upgradeUser(0);
      passAll = passAll & testUserBase.getUserTable().get(0).isAdmin();
      System.out.println("User successfully upgraded to admin.");
*/
      return passAll;
    }
}
